package org.juhewu.file.core.storage;

import cn.hutool.core.lang.Assert;
import lombok.Data;
import org.csource.fastdfs.*;
import org.juhewu.file.core.FileInfo;
import org.juhewu.file.core.UploadPretreatment;
import org.juhewu.file.core.exception.FileStorageException;
import org.juhewu.file.core.storage.config.BaseConfig;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Properties;
import java.util.function.Consumer;

public class FastDFSFileStorage implements FileStorage {

    private final FastDFS fastDFS;


    public FastDFSFileStorage(FastDFS fastDFS) {
        this.fastDFS = fastDFS;
        initFastDFSClient();
    }

    private void initFastDFSClient() {
        Properties properties = initFastDfsProperties();
        try {
            ClientGlobal.initByProperties(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 唯一 id
     */
    @Override
    public String getStorageId() {
        return fastDFS.getStorageId();
    }

    /**
     * 上传文件
     *
     * @param fileInfo
     * @param pre
     * @return
     */
    @Override
    public boolean upload(FileInfo fileInfo, UploadPretreatment pre) {
        try {
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            StorageServer storageServer = null;
            StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer);
            // 字节数组，拓展名，额外参数
            String s = storageClient1.upload_file1(pre.getFileWrapper().getBytes(),
                    fileInfo.getExt(), null);
            fileInfo.setPath(s);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 删除文件
     *
     * @param fileInfo
     */
    @Override
    public boolean delete(FileInfo fileInfo) {
        try {
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            StorageServer storageServer = null;
            StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer);
            String path = fileInfo.getPath();
            Assert.notNull(path);
            storageClient1.delete_file1(path);
            return true;
        } catch (Exception e) {
            throw new FileStorageException("文件删除失败!" + fileInfo, e);
        }
    }


    /**
     * 文件是否存在
     *
     * @param fileInfo
     */
    @Override
    public boolean exists(FileInfo fileInfo) {
        try {
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            StorageServer storageServer = null;
            StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer);
            String path = fileInfo.getPath();
            Assert.notNull(path);
            org.csource.fastdfs.FileInfo file_info1 = storageClient1.get_file_info1(path);
            if (file_info1 != null) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            throw new FileStorageException("文件删除失败!" + fileInfo, e);
        }
    }

    /**
     * 下载文件
     *
     * @param fileInfo
     * @param consumer
     */
    @Override
    public void download(FileInfo fileInfo, Consumer<InputStream> consumer) {
        ByteArrayInputStream in = null;
        try {
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            StorageServer storageServer = null;
            StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer);
            String path = fileInfo.getPath();
            Assert.notNull(path);
            String[] fileId = new String[2];
            StorageClient1.split_file_id(path, fileId);
            byte[] downloadFile = storageClient1.download_file(fileId[0], fileId[1]);
            in = new ByteArrayInputStream(downloadFile);
            consumer.accept(in);
        } catch (Exception e) {
            throw new FileStorageException("文件下载失败！platform：" + fileInfo, e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 下载缩略图文件
     *
     * @param fileInfo
     * @param consumer
     */
    @Override
    public void downloadTh(FileInfo fileInfo, Consumer<InputStream> consumer) {
        ByteArrayInputStream in = null;
        try {
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getTrackerServer();
            StorageServer storageServer = null;
            StorageClient1 storageClient1 = new StorageClient1(trackerServer, storageServer);
            String path = fileInfo.getPath();
            Assert.notNull(path);
            String[] fileId = new String[2];
            StorageClient1.split_file_id(path, fileId);
            byte[] downloadFile = storageClient1.download_file(fileId[0], fileId[1]);
            in = new ByteArrayInputStream(downloadFile);
            consumer.accept(in);
        } catch (Exception e) {
            throw new FileStorageException("文件下载失败！platform：" + fileInfo, e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private Properties initFastDfsProperties() {
        String charSet = fastDFS.getCharSet();
        String connectTimeout = fastDFS.getConnectTimeout();
        String networkTimeout = fastDFS.getNetworkTimeout();
        String httpSecretKey = fastDFS.getHttpSecretKey();
        String trackerServers = fastDFS.getTrackerServers();
        String httpTrackerHttpPort = fastDFS.getHttpTrackerHttpPort();
        String httpAntiStealToken = fastDFS.getHttpAntiStealToken();
        String connectionPoolEnabled = fastDFS.getConnectionPoolEnabled();
        String connectionPoolMaxCountPerEntry = fastDFS.getConnectionPoolMaxCountPerEntry();
        String connectionPoolMaxIdleTimeSeconds = fastDFS.getConnectionPoolMaxIdleTimeSeconds();
        String connectionPoolMaxWaitTimeInMs = fastDFS.getConnectionPoolMaxWaitTimeInMs();
        Properties properties = new Properties();
        properties.put("fastdfs.tracker_servers", trackerServers);
        properties.put("fastdfs.connect_timeout_in_seconds", connectTimeout);
        properties.put("fastdfs.network_timeout_in_seconds", networkTimeout);
        properties.put("fastdfs.charset", charSet);
        properties.put("fastdfs.http_anti_steal_token", httpAntiStealToken);
        properties.put("fastdfs.http_secret_key", httpSecretKey);
        properties.put("fastdfs.http_tracker_http_port", httpTrackerHttpPort);
        properties.put("fastdfs.connection_pool.enabled", connectionPoolEnabled);
        properties.put("fastdfs.connection_pool.max_count_per_entry", connectionPoolMaxCountPerEntry);
        properties.put("fastdfs.connection_pool.max_idle_time", connectionPoolMaxIdleTimeSeconds);
        properties.put("fastdfs.connection_pool.max_wait_time_in_ms", connectionPoolMaxWaitTimeInMs);
        return properties;
    }


    /**
     * FastDFS
     */
    @Data
    public static class FastDFS extends BaseConfig {

        private String httpAntiStealToken = "false";
        private String httpSecretKey = "";
        private String groupName = "";

        /**
         * 追踪器服务端口
         */
        private String httpTrackerHttpPort = "";
        /**
         * 追踪器服务端口
         */
        private String trackerServers = "";
        private String charSet = "";

        private String connectTimeout = "";
        private String networkTimeout = "";
        private String connectionPoolEnabled = "";
        private String connectionPoolMaxCountPerEntry = "";
        private String connectionPoolMaxIdleTimeSeconds = "";
        private String connectionPoolMaxWaitTimeInMs = "";

    }
}
